/**
 * Socket.io 全局单例事件工具 for Vue 3
 * 提供全局单例Socket连接，可以在各个组件中使用
 * 注意：需要先在index.html中引入socket.io.min.js
 */
import { ref } from 'vue'
import { getSocketUrl } from '@/api/system'
import UrlStorage from './urlStorage' // 引入封装的工具
// 用于存储全局唯一实例
let _singleton = null

// Socket URL将从API获取
let SOCKET_URL = null

// 默认Socket URL，可在使用时覆盖
// 开发环境：空字符串让socket.io连接到当前origin（通过代理转发）
// 生产环境：从环境变量读取，如果没有则使用默认值
const DEFAULT_SOCKET_URL = import.meta.env.PROD
  ? (import.meta.env.VITE_APP_SOCKET_URL || 'https://socket.zhzylz.icu')
  : '' // 空字符串会自动连接到当前origin，由vite代理转发

  const getTradeNo = () => {
    // 1. 从URL/Hash参数获取（复用工具方法）
    const tradeNo = UrlStorage.getUrlParam('trade_no') ||UrlStorage.getUrlParam('orderId') ||  UrlStorage.getUrlParam('order_no')
    
    if (tradeNo) {
      // 2. 缓存到localStorage（无过期时间）
      UrlStorage.setStorage('trade_no', tradeNo)
      console.log('[Socket.js] 从URL/Hash获取trade_no:', tradeNo)
      return tradeNo
    }
  
    // 3. 从localStorage读取缓存
    const storedTradeNo = UrlStorage.getStorage('trade_no')
    if (storedTradeNo) {
      console.log('[Socket.js] 从localStorage读取trade_no:', storedTradeNo)
      return storedTradeNo
    }
  
    console.log('[Socket.js] 未找到trade_no（URL/Hash/localStorage均无）')
    return ''
  }
  
export default function useSocket(url = DEFAULT_SOCKET_URL, options = {}) {
  // 已有单例就直接返回
  if (_singleton) return _singleton

  // Vue 3 中使用 ref 实现响应式
  const socket = ref(null)
  const connected = ref(false)
  const connecting = ref(false)
  const error = ref(null)
  const listeners = ref(new Map())

  // 连接方法
  const connect = async () => {
    // 如果已经在连接中，直接返回
    if (connecting.value) {
      console.log('[Socket.js] 正在连接中，跳过重复连接')
      return
    }
    
    // 如果已经连接，先断开
    if (socket.value?.connected) {
      console.log('[Socket.js] 检测到已连接，先断开旧连接')
      socket.value.disconnect()
      socket.value = null
    }
    
    if (typeof window === 'undefined' || !window.io) {
      error.value = new Error('Socket.io 未加载，请确保已引入 socket.io.min.js')
      console.error('[Socket.js] Socket.io 未加载');
      return
    }
    
    connecting.value = true
    error.value = null
    
    try {
      // 先获取Socket地址
      let socketUrl = SOCKET_URL
      if (!socketUrl) {
        console.log('SOCKET_URL',SOCKET_URL)
        console.log('[Socket.js] 正在从API获取Socket地址...----------12312----------')
        try {
          const tradeNo = getTradeNo();

          const response = await getSocketUrl( { trade_no: tradeNo })
          if (response && response.code === 1  && response.url) {
            socketUrl = response.url
            // eslint-disable-next-line require-atomic-updates
            SOCKET_URL = socketUrl // 缓存URL
            console.log('[Socket.js] 成功获取Socket地址:', socketUrl)
          } else {
            console.error('asdfasdfs------------')
            console.warn('[Socket.js] 获取Socket地址失败，使用默认地址')
            socketUrl = url || DEFAULT_SOCKET_URL
            // eslint-disable-next-line require-atomic-updates
            SOCKET_URL = socketUrl // 缓存URL
          }
        } catch (error) {
          console.error('[Socket.js] 获取Socket地址异常:', error)
          console.warn('[Socket.js] 使用默认地址')
          socketUrl = url || DEFAULT_SOCKET_URL
          // eslint-disable-next-line require-atomic-updates
          SOCKET_URL = socketUrl // 缓存URL
        }
      }
      
      console.log('[Socket.js] 创建Socket实例，URL:', socketUrl || '(当前origin)');
      console.log('[Socket.js] 配置:', { transports: ['websocket', 'polling'], path: '/socket.io', ...options });
      console.log('socketUrl==============',socketUrl)
      // 创建socket实例
      const newSocket = window.io(socketUrl, {
        transports: ['websocket', 'polling'],
        autoConnect: true, // 自动连接
        reconnection: true,
        reconnectionAttempts: 5,
        reconnectionDelay: 1000,
        reconnectionDelayMax: 5000,
        timeout: 20000,
        path: '/socket.io',
        ...options
      })
      
      console.log('[Socket.js] Socket实例已创建');
      
      // 内部状态管理 - 使用原始的on方法，不影响外部监听器
      const originalOn = newSocket.on.bind(newSocket)
      
      // 注册内部监听器来更新状态
      originalOn('connect', () => {
        console.log('[Socket.js 内部状态] connect事件触发，Socket ID:', newSocket.id);
        connected.value = true
        connecting.value = false
        error.value = null
      })
      
      originalOn('connect_error', (err) => {
        console.error('[Socket.js 内部状态] 连接错误:', err.message || err);
        connected.value = false
        connecting.value = false
        error.value = err
      })
      
      originalOn('disconnect', (reason) => {
        console.log('[Socket.js 内部状态] 连接断开，原因:', reason);
        connected.value = false
        connecting.value = false
      })
      
      originalOn('reconnect_failed', () => {
        console.log('[Socket.js 内部状态] 重连失败');
        connecting.value = false
      })
      
      // 注册所有待注册的监听器（关键！）
      console.log('[Socket.js] 注册待处理的监听器，数量:', listeners.value.size);
      listeners.value.forEach((callbacks, event) => {
        callbacks.forEach(callback => {
          console.log('[Socket.js] 注册待处理监听器:', event)
          newSocket.on(event, callback)
        })
      })
      
      // 最后赋值给socket.value
      // eslint-disable-next-line require-atomic-updates
      socket.value = newSocket
      console.log('[Socket.js] Socket实例准备完毕，等待连接...');
      
    } catch (err) {
      console.error('[Socket.js] 连接异常------------------:', err);
      // eslint-disable-next-line require-atomic-updates
      connecting.value = false
      // eslint-disable-next-line require-atomic-updates
      error.value = err
    }
  }

  // 断开连接
  const disconnect = () => {
    if (socket.value) {
      clearAllListeners()
      socket.value.disconnect()
      socket.value = null
      connected.value = false
      connecting.value = false
    }
  }

  // 发送消息
  const emit = (event, ...args) => {
    if (!socket.value || !connected.value) return false
    try {
      socket.value.emit(event, ...args)
      return true
    } catch (err) {
      return false
    }
  }

  // 监听事件（延迟注册机制）
  const on = (event, callback) => {
    // 先记录监听器到Map
    if (!listeners.value.has(event)) {
      listeners.value.set(event, [])
    }
    
    const callbacks = listeners.value.get(event)
    
    // 检查是否已经存在，避免重复添加
    if (callbacks.includes(callback)) {
      console.log('[Socket.js] 监听器已存在，跳过:', event)
      return () => off(event, callback)
    }
    
    // 添加到记录中
    callbacks.push(callback)
    
    // 如果socket已创建，立即注册
    if (socket.value) {
      console.log('[Socket.js] 立即添加事件监听器:', event)
      socket.value.on(event, callback)
    } else {
      // 如果socket未创建，先存储回调，等socket创建后再注册
      console.log('[Socket.js] Socket未创建，存储监听器待注册:', event)
    }
    
    // 返回取消监听的函数
    return () => off(event, callback)
  }

  // 只监听一次
  const once = (event, callback) => {
    if (!socket.value) return
    socket.value.once(event, callback)
  }

  // 取消事件监听
  const off = (event, callback) => {
    if (!socket.value) return
    if (callback) {
      socket.value.off(event, callback)
      const arr = listeners.value.get(event)
      if (arr) {
        const index = arr.indexOf(callback)
        if (index !== -1) arr.splice(index, 1)
      }
      if (arr && arr.length === 0) listeners.value.delete(event)
    } else {
      socket.value.off(event)
      listeners.value.delete(event)
    }
  }

  // 移除所有事件
  const clearAllListeners = () => {
    if (!socket.value) return
    listeners.value.forEach((arr, event) => {
      arr.forEach(cb => socket.value.off(event, cb))
    })
    listeners.value.clear()
    socket.value.off('connect')
    socket.value.off('disconnect')
    socket.value.off('error')
  }

  // 获取id
  const getSocketId = () => {
    return socket.value?.id || null
  }

  // 重置Socket URL（强制重新从API获取）
  const resetSocketUrl = () => {
    console.log('[Socket.js] 重置Socket URL')
    SOCKET_URL = null
  }

  // 单例对象内暴露接口
  _singleton = {
    socket,
    connected,
    connecting,
    error,
    connect,
    disconnect,
    emit,
    on,
    once,
    off,
    clearAllListeners,
    getSocketId,
    resetSocketUrl
  }
  
  return _singleton
}

// 创建默认实例
export const socketInstance = useSocket()

// 创建Vue插件
export const SocketPlugin = {
  install(app) {
    app.config.globalProperties.$socket = socketInstance
  }
}
